import { ref, computed } from 'vue'

/**
 * 文件分片上传的 useChunkedUpload
 * @param uploadFileApi 上传接口函数
 * @param chunkSize 分片大小（默认：1MB）
 * @param concurrency 并发数（默认：3）
 * @returns 返回上传相关的方法和状态
 */
export function useChunkedUpload(
    uploadFileApi: (formData: FormData, index: number, controller: AbortController) => Promise<void>,
    chunkSize: number = 1024 * 1024,
    concurrency: number = 3
) {
    const file = ref<File | null>(null)
    const uploadTotal = ref(0)
    const progress = ref(0)
    const isUploading = ref(false)
    const isPaused = ref(false)
    const error = ref<Error | null>(null)

    // 分片上传任务队列
    const queue = ref<Array<{ chunk: Blob; index: number }>>([])
    const activeTasks = ref<{ key: number; query: Promise<void>; controller: AbortController }[]>([])

    // 计算已上传的字节数
    const uploadedBytes = computed(() => (progress.value / 100) * (file.value?.size || 0))

    // 分片文件
    const chunkFile = (file: File) => {
        const chunks = []
        let start = 0
        while (start < file.size) {
            const end = Math.min(start + chunkSize, file.size)
            chunks.push(file.slice(start, end))
            start = end
        }
        return chunks
    }

    // 上传单个分片
    const uploadChunk = async (chunk: Blob, index: number, controller: AbortController) => {
        const formData = new FormData()
        formData.append('chunk', chunk)
        formData.append('chunkIndex', index.toString())
        formData.append('totalChunks', uploadTotal.value.toString())
        formData.append('fileName', file.value?.name || '')

        try {
            await uploadFileApi(formData, index, controller)
        } catch (err) {
            const { message } = err as { message: string }
            throw new Error(`分片 ${index} 上传失败: ${message}`)
        }
    }

    // 处理上传任务
    const processQueue = async () => {
        while (queue.value.length > 0 && activeTasks.value.length < concurrency) {
            if (isPaused.value) break

            const { chunk, index } = queue.value.shift()!

            const controller = new AbortController()

            const task = uploadChunk(chunk, index, controller)
                .then(() => {
                    progress.value = ((index + 1) / uploadTotal.value) * 100
                })
                .catch((err) => {
                    error.value = err
                })
                .finally(() => {
                    activeTasks.value = activeTasks.value.filter(({ key }) => key !== index)
                    processQueue() // 继续处理队列
                })

            activeTasks.value.push({ key: index, query: task, controller })
        }

        // 如果队列为空且没有活跃任务，上传完成
        if (queue.value.length === 0 && activeTasks.value.length === 0) {
            isUploading.value = false
            console.log('上传完成', '总分片数量：' + uploadTotal.value)
        }
    }

    // 开始上传
    const startUpload = async () => {
        const selectedFile = file.value as File
        if (!selectedFile) {
            error.value = new Error('请选择文件')
            return
        }

        isUploading.value = true
        isPaused.value = false
        error.value = null
        progress.value = 0

        // 分片文件
        const chunks = chunkFile(selectedFile)
        uploadTotal.value = chunks.length

        queue.value = chunks.map((chunk, index) => ({ chunk, index }))

        console.log('开始上传', '总分片数量：' + uploadTotal.value)

        await processQueue()
    }

    // 暂停上传
    const pauseUpload = () => {
        isPaused.value = true
    }

    // 继续上传
    const resumeUpload = () => {
        if (!isUploading.value || !isPaused.value) return
        isPaused.value = false
        processQueue()
    }

    // 重试上传
    const retryUpload = () => {
        if (!file.value) return
        startUpload()
    }

    // 取消上传
    const cancelUpload = () => {
        if (!isUploading.value) return

        // 取消所有活跃任务
        activeTasks.value.forEach(({ controller }) => controller.abort())
        activeTasks.value = []
        queue.value = []

        // 重置状态
        progress.value = 0
        uploadTotal.value = 0
        isUploading.value = false
        isPaused.value = false
        error.value = new Error('上传已取消')
    }

    return {
        file,
        progress,
        isUploading,
        isPaused,
        error,
        uploadedBytes,
        startUpload,
        pauseUpload,
        resumeUpload,
        retryUpload,
        cancelUpload
    }
}
